home *** CD-ROM | disk | FTP | other *** search
/ Aminet 37 / Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso / Aminet / dev / lang / sofa.lha / sofa / smalleiffel / lib_se / e_when.e < prev    next >
Text File  |  2000-03-25  |  13KB  |  496 lines

  1. --          This file is part of SmallEiffel The GNU Eiffel Compiler.
  2. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  3. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr
  4. --                       http://SmallEiffel.loria.fr
  5. -- SmallEiffel is  free  software;  you can  redistribute it and/or modify it
  6. -- under the terms of the GNU General Public License as published by the Free
  7. -- Software  Foundation;  either  version  2, or (at your option)  any  later
  8. -- version. SmallEiffel is distributed in the hope that it will be useful,but
  9. -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. -- or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU General Public License
  11. -- for  more  details.  You  should  have  received a copy of the GNU General
  12. -- Public  License  along  with  SmallEiffel;  see the file COPYING.  If not,
  13. -- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  14. -- Boston, MA 02111-1307, USA.
  15. --
  16. class E_WHEN
  17.    --
  18.    -- To store a when clause of an inspect instruction.
  19.    --
  20.  
  21. inherit GLOBALS;
  22.  
  23. creation {EIFFEL_PARSER}
  24.    make
  25.  
  26. creation {E_WHEN,WHEN_LIST}
  27.    from_e_when
  28.  
  29. feature
  30.  
  31.    start_position: POSITION;
  32.          -- Of the first character of keyword "when".
  33.  
  34. feature {E_WHEN}
  35.  
  36.    list: ARRAY[WHEN_ITEM];
  37.  
  38. feature
  39.  
  40.    header_comment: COMMENT;
  41.          -- Of the when clause.
  42.  
  43.    compound: COMPOUND;
  44.          -- Of the when clause if any.
  45.  
  46.    when_list: WHEN_LIST;
  47.          -- Corresponding one when checked.
  48.  
  49.    values: ARRAY[BOOLEAN];
  50.          -- True when the corresponding index is in the when.
  51.  
  52. feature {NONE}
  53.  
  54.    points1: FIXED_ARRAY[INTEGER] is
  55.          -- To reach the `compound'.
  56.       once
  57.          !!Result.with_capacity(12);
  58.       end;
  59.  
  60.    point2: INTEGER;
  61.          -- To go outside the E_INSPECT.
  62.  
  63. feature {EIFFEL_PARSER}
  64.  
  65.    make(sp: like start_position; hc: like header_comment) is
  66.       require
  67.          not sp.is_unknown
  68.       do
  69.          start_position := sp;
  70.          header_comment := hc;
  71.       ensure
  72.          start_position = sp;
  73.       end;
  74.  
  75. feature {WHEN_LIST}
  76.  
  77.    afd_check is
  78.       do
  79.          if compound /= Void then
  80.             compound.afd_check;
  81.          end;
  82.       end;
  83.  
  84. feature {NONE}
  85.  
  86.    from_e_when(other: like Current) is
  87.       local
  88.          i: INTEGER;
  89.          when_item: WHEN_ITEM;
  90.       do
  91.          start_position := other.start_position;
  92.          list := other.list.twin;
  93.          from
  94.             i := list.lower;
  95.          until
  96.             i > list.upper
  97.          loop
  98.             when_item := list.item(i).twin;
  99.             when_item.clear_e_when;
  100.             list.put(when_item,i);
  101.             i := i + 1;
  102.          end;
  103.          header_comment := other.header_comment;
  104.          compound := other.compound;
  105.       end;
  106.  
  107. feature
  108.  
  109.    use_current: BOOLEAN is
  110.       do
  111.          if compound /= Void then
  112.             Result := compound.use_current;
  113.          end;
  114.       end;
  115.  
  116.    stupid_switch(r: ARRAY[RUN_CLASS]): BOOLEAN is
  117.       do
  118.          Result := (compound = Void or else compound.stupid_switch(r));
  119.       end;
  120.  
  121.    e_inspect: E_INSPECT is
  122.       do
  123.          Result := when_list.e_inspect;
  124.       end;
  125.  
  126. feature {WHEN_LIST}
  127.  
  128.    compile_to_jvm(else_position: POSITION; remainder: INTEGER) is
  129.          -- Where `remainder' is the number of E_WHEN after Current.
  130.       local
  131.          point3, point4, bi, bs: INTEGER;
  132.          must_test: BOOLEAN;
  133.          ca: like code_attribute;
  134.       do
  135.          ca := code_attribute;
  136.          if remainder > 0 then
  137.             must_test := true;
  138.          elseif run_control.no_check then
  139.             must_test := true;
  140.          else -- boost :
  141.             must_test := not else_position.is_unknown;
  142.          end;
  143.          points1.clear;
  144.          if must_test then
  145.             from
  146.                bi := values.lower;
  147.             until
  148.                bi > values.upper
  149.             loop
  150.                from
  151.                   bs := bi + 1;
  152.                until
  153.                   bs > values.upper or else not values.item(bs)
  154.                loop
  155.                   bs := bs + 1;
  156.                end;
  157.                bs := bs - 1;
  158.                --
  159.                if bi = bs then
  160.                   ca.opcode_dup;
  161.                   ca.opcode_push_integer(bi);
  162.                   points1.add_last(ca.opcode_if_icmpeq);
  163.                else
  164.                   ca.opcode_dup;
  165.                   ca.opcode_push_integer(bi);
  166.                   point3 := ca.opcode_if_icmplt;
  167.                   ca.opcode_dup;
  168.                   ca.opcode_push_integer(bs);
  169.                   points1.add_last(ca.opcode_if_icmple);
  170.                   ca.resolve_u2_branch(point3);
  171.                end;
  172.                from
  173.                   bi := bs + 1;
  174.                until
  175.                   bi > values.upper or else values.item(bi)
  176.                loop
  177.                   bi := bi + 1;
  178.                end;
  179.             end;
  180.             point4 := ca.opcode_goto;
  181.          end;
  182.          ca.resolve_with(points1);
  183.          if compound /= Void then
  184.             compound.compile_to_jvm;
  185.          end;
  186.          point2 := ca.opcode_goto;
  187.          if must_test then
  188.             ca.resolve_u2_branch(point4);
  189.          end;
  190.       end;
  191.  
  192.    compile_to_jvm_resolve_branch is
  193.       do
  194.          code_attribute.resolve_u2_branch(point2);
  195.       end;
  196.  
  197.    compile_to_c is
  198.       local
  199.          bi, bs: INTEGER;
  200.       do
  201.          cpp.put_string("%Nif(");
  202.          from
  203.             bi := values.lower;
  204.          until
  205.             bi > values.upper
  206.          loop
  207.             from
  208.                bs := bi + 1;
  209.             until
  210.                bs > values.upper or else not values.item(bs)
  211.             loop
  212.                bs := bs + 1;
  213.             end;
  214.             bs := bs - 1;
  215.             --
  216.             cpp.put_character('(');
  217.             if bi = bs then
  218.                cpp.put_integer(bi);
  219.                cpp.put_string("==");
  220.                cpp.put_inspect;
  221.             else
  222.                cpp.put_character('(');
  223.                cpp.put_integer(bi);
  224.                cpp.put_string("<=");
  225.                cpp.put_inspect;
  226.                cpp.put_string(")&&(");
  227.                cpp.put_inspect;
  228.                cpp.put_string("<=");
  229.                cpp.put_integer(bs);
  230.                cpp.put_character(')');
  231.             end;
  232.             cpp.put_character(')');
  233.             --
  234.             from
  235.                bi := bs + 1;
  236.             until
  237.                bi > values.upper or else values.item(bi)
  238.             loop
  239.                bi := bi + 1;
  240.             end;
  241.             if bi <= values.upper then
  242.                cpp.put_string("||");
  243.             end;
  244.          end;
  245.          cpp.put_string("){%N");
  246.          if compound /= Void then
  247.             compound.compile_to_c;
  248.          end;
  249.          cpp.put_string(fz_12);
  250.       end;
  251.  
  252.    pretty_print is
  253.       local
  254.          i: INTEGER;
  255.       do
  256.          fmt.keyword(fz_when);
  257.          fmt.level_incr;
  258.          if header_comment /= Void then
  259.             header_comment.pretty_print;
  260.          end;
  261.          if list /= Void then
  262.             from
  263.                i := list.lower;
  264.             until
  265.                i > list.upper
  266.             loop
  267.                list.item(i).pretty_print;
  268.                i := i + 1;
  269.                if i <= list.upper then
  270.                   fmt.put_character(',');
  271.                end;
  272.             end;
  273.          end;
  274.          fmt.level_decr;
  275.          fmt.keyword(fz_then);
  276.          fmt.level_incr;
  277.          if compound /= Void then
  278.             compound.pretty_print;
  279.          end;
  280.          fmt.level_decr;
  281.       end;
  282.  
  283.    includes_integer(v: INTEGER): BOOLEAN is
  284.       do
  285.          Result := ((values /= Void) and then
  286.                     values.valid_index(v) and then
  287.                     values.item(v));
  288.       end;
  289.  
  290. feature {WHEN_LIST,E_WHEN}
  291.  
  292.    to_runnable_integer(wl: like when_list): like Current is
  293.       require
  294.          wl /= Void;
  295.       local
  296.          ct: TYPE;
  297.          ne, i: INTEGER;
  298.          when_item: WHEN_ITEM;
  299.       do
  300.          if when_list = Void then
  301.             ne := nb_errors;
  302.             when_list := wl;
  303.             if list = Void then
  304.                eh.add_position(e_inspect.start_position);
  305.                error(start_position,em2);
  306.             else
  307.                from
  308.                   i := list.lower;
  309.                until
  310.                   i > list.upper or else nb_errors - ne > 0
  311.                loop
  312.                   when_item := list.item(i).to_runnable_integer(Current);
  313.                   if when_item = Void then
  314.                      error(start_position,em1);
  315.                   else
  316.                      list.put(when_item,i);
  317.                   end;
  318.                   i := i + 1;
  319.                end;
  320.             end;
  321.             if compound /= Void then
  322.                ct := small_eiffel.top_rf.current_type;
  323.                compound := compound.to_runnable(ct);
  324.                if compound = Void then
  325.                   error(start_position,em1);
  326.                end;
  327.             end;
  328.             Result := Current;
  329.          else
  330.             !!Result.from_e_when(Current);
  331.             Result := Result.to_runnable_integer(wl);
  332.          end;
  333.       ensure
  334.          Result.when_list = wl
  335.       end;
  336.  
  337.    to_runnable_character(wl: like when_list): like Current is
  338.       require
  339.          wl /= Void;
  340.       local
  341.          ct: TYPE;
  342.          ne, i: INTEGER;
  343.          when_item: WHEN_ITEM;
  344.       do
  345.          if when_list = Void then
  346.             ne := nb_errors;
  347.             when_list := wl;
  348.             if list = Void then
  349.                eh.add_position(e_inspect.start_position);
  350.                error(start_position,em2);
  351.             else
  352.                from
  353.                   i := list.lower;
  354.                until
  355.                   i > list.upper or else nb_errors - ne > 0
  356.                loop
  357.                   when_item := list.item(i).to_runnable_character(Current);
  358.                   if when_item = Void then
  359.                      error(start_position,em1);
  360.                   else
  361.                      list.put(when_item,i);
  362.                   end;
  363.                   i := i + 1;
  364.                end;
  365.             end;
  366.             if compound /= Void then
  367.                ct := small_eiffel.top_rf.current_type;
  368.                compound := compound.to_runnable(ct);
  369.                if compound = Void then
  370.                   error(start_position,em1);
  371.                end;
  372.             end;
  373.             Result := Current;
  374.          else
  375.             !!Result.from_e_when(Current);
  376.             Result := Result.to_runnable_character(wl);
  377.          end;
  378.       ensure
  379.          Result.when_list = wl
  380.       end;
  381.  
  382. feature {WHEN_ITEM_1}
  383.  
  384.    add_when_item_1(wi1: WHEN_ITEM_1) is
  385.       require
  386.          wi1 /= Void
  387.       local
  388.          v: INTEGER;
  389.       do
  390.          v := wi1.expression_value;
  391.          if e_inspect.includes(v) then
  392.             err_occ(v,wi1.start_position);
  393.          elseif values = Void then
  394.             !!values.make(v,v);
  395.             values.put(true,v);
  396.          else
  397.             values.force(true,v);
  398.          end;
  399.       ensure
  400.          e_inspect.includes(wi1.expression_value);
  401.       end;
  402.  
  403. feature {WHEN_ITEM_2}
  404.  
  405.    add_when_item_2(wi2: WHEN_ITEM_2) is
  406.       require
  407.          wi2 /= Void
  408.       local
  409.          l, u, i: INTEGER;
  410.       do
  411.          l := wi2.lower_value;
  412.          u := wi2.upper_value;
  413.          if l >= u then
  414.             error(wi2.start_position,"Not a good slice.");
  415.          end;
  416.          if nb_errors = 0 then
  417.             from
  418.                i := l;
  419.             until
  420.                i > u
  421.             loop
  422.                if e_inspect.includes(i) then
  423.                   err_occ(i,wi2.start_position);
  424.                   i := u + 1;
  425.                else
  426.                   i := i + 1;
  427.                end;
  428.             end;
  429.          end;
  430.          if nb_errors = 0 then
  431.             if values = Void then
  432.                !!values.make(l,u);
  433.                values.set_all_with(true);
  434.             else
  435.                values.force(true,l);
  436.                values.force(true,u);
  437.                values.set_slice_with(true,l,u);
  438.             end;
  439.          end;
  440.       end;
  441.  
  442. feature {EIFFEL_PARSER}
  443.  
  444.    add_value(v: EXPRESSION) is
  445.       require
  446.          v /= Void;
  447.       local
  448.          element: WHEN_ITEM
  449.       do
  450.          !WHEN_ITEM_1!element.make(v);
  451.          if list = Void then
  452.             !!list.with_capacity(4,1);
  453.      end;
  454.      list.add_last(element);
  455.       end;
  456.  
  457.    add_slice(min, max: EXPRESSION) is
  458.       require
  459.          min /= Void;
  460.          max /= Void;
  461.       local
  462.          element: WHEN_ITEM;
  463.       do
  464.          !WHEN_ITEM_2!element.make(min,max);
  465.          if list = Void then
  466.             !!list.with_capacity(4,1);
  467.          end;
  468.      list.add_last(element);
  469.       end;
  470.  
  471.    set_compound(c: like compound) is
  472.       do
  473.          compound := c;
  474.       ensure
  475.          compound = c
  476.       end;
  477.  
  478. feature {NONE}
  479.  
  480.    err_occ(v: INTEGER; p: POSITION) is
  481.       do
  482.          eh.add_position(e_inspect.start_position);
  483.          eh.append("Second occurrence for this value (");
  484.          eh.append(v.to_string);
  485.          error(p,") in the same inspect.");
  486.       end;
  487.  
  488. feature {NONE}
  489.  
  490.    em1: STRING is "Bad when clause.";
  491.    em2: STRING is "Empty when clause in inspect.";
  492.  
  493. end -- E_WHEN
  494.  
  495.  
  496.